#include "../include/ast.h"
#include "../include/main.h"
#include <cstring>

using namespace std;
ast *node;
char *whichFunc;
char *whichVarDecl;

past ast::newAstNode(char *nodeType) {
    if (strcmp(nodeType, "CompUnit") == 0) {
        node = new CompUnit();
    } else if (strcmp(nodeType, "Decl") == 0) {
        node = new Decl();
    } else if (strcmp(nodeType, "VarDecl") == 0) {
        node = new VarDecl();
    } else if (strcmp(nodeType, "VarDef") == 0) {
        node = new VarDef();
    } else if (strcmp(nodeType, "FuncDef") == 0) {
        node = new FuncDef();
    } else if (strcmp(nodeType, "UnaryExp") == 0) {
        node = new UnaryExp();
    } else if (strcmp(nodeType, "If_Else") == 0) {
        node = new If_Else();
    } else if (strcmp(nodeType, "IfElse_Stmt") == 0) {
        node = new IfElse_Stmt();
    } else if (strcmp(nodeType, "VarDecl_list") == 0) {
        node = new VarDecl_list();
    } else if (strcmp(nodeType, "FuncRParams_list") == 0) {
        node = new FuncRParams_list();
    } else if (strcmp(nodeType, "FuncDef_para") == 0) {
        node = new FuncDef_para();
    } else if (strcmp(nodeType, "Block_list") == 0) {
        node = new Block_list();
    } else if (strcmp(nodeType, "While_Stmt") == 0) {
        node = new While_Stmt();
    } else if (strcmp(nodeType, "Assign_Stmt") == 0) {
        node = new Assign_Stmt();
    } else if (strcmp(nodeType, "Return_Stmt") == 0) {
        node = new Return_Stmt();
    } else node = new CompUnit();
    return node;
}

past ast::newNum(int value) {
    past var = new intValue;
    var->nodeType = (char *) "intValue";
    var->ivalue = value;
    return var;
}

past ast::newExpr(int oper, past left, past right) {
    past var = new expr;
    var->nodeType = (char *) "expr";
    var->ivalue = oper;
    var->left = left;
    var->right = right;
    var->strValue = (char *) "@";
    return var;
}

past ast::newDoubleExpr(char *logic_oper, past left, past right) {
    past var = new expr;
    var->nodeType = (char *) "expr";
    char *strVal = new char;
    strcpy(strVal, logic_oper);
    var->strValue = strVal;
    var->left = left;
    var->right = right;
    return var;
}

past ast::newBasicNode(char *nodeType, past left, past right, past next) {
    char *node_type = new char;
    strcpy(node_type, nodeType);
    past root = newAstNode(node_type);
    root->nodeType = node_type;
    root->left = left;
    root->right = right;
    root->next = next;
    return root;
}

past ast::newNextNode(char *nodeType, past older, past younger) {
    past root = nullptr;
    //还没有根节点

    if (strcmp(nodeType, older->nodeType) != 0) {
        char *node_type = new char;
        strcpy(node_type, nodeType);
        root = newAstNode(node_type);
        root->nodeType = node_type;
        root->left = older;
        root->left->next = younger;
        root->ivalue = 1;
    }
        //已经有根节点
    else {
        root = older;
        older = older->left;
        while (older->next != nullptr) older = older->next;
        older->next = younger;
        root->ivalue++;
    }
    return root;
}

past ast::newTypeNode(char *strVal) {
    past root = new type;
    root->nodeType = (char *) "type";
    char *buf = new char;
    strcpy(buf, strVal);
    root->strValue = buf;
    return root;
}

past ast::newIDNode(char *strVal) {
    past root = new parameter;
    root->nodeType = (char *) "parameter";
    char *buf = new char;
    strcpy(buf, strVal);
    root->strValue = buf;
    return root;
}

void ast::showAst(past node, int nest) {
    if (node == nullptr) {
//         cout<<"node transfer error"<<endl;
        return;
    }
    for (int i = 0; i < nest; i++)
        cout << "  ";
    if (strcmp(node->nodeType, "expr") == 0) {
        if (strcmp(node->strValue, "@") == 0)
            cout << node->nodeType << " " << (char) node->ivalue << endl;
        else
            cout << node->nodeType << " " << node->strValue << endl;
    } else if (strcmp(node->nodeType, "intValue") == 0) {
        cout << node->nodeType << " . " << node->ivalue << endl;
    } else {
        if (!node->strValue) {
            if (node->ivalue) cout << node->nodeType << " . " << node->ivalue << endl;
            else cout << node->nodeType << " ." << endl;
        } else if (node->ivalue) cout << node->nodeType << " " << node->strValue << " " << node->ivalue << endl;
        else cout << node->nodeType << " " << node->strValue << " ." << endl;
    }
    showAst(node->left, nest + 1);
    showAst(node->right, nest + 1);
    showAst(node->next, nest);
}

void ast::genSym(past node) {
    if (node == nullptr) {
//        cout<<"node transfer error"<<endl;
        return;
    }
    BuildSym v(node);
    node->accept(&v);
    genSym(node->left);
    genSym(node->right);
    genSym(node->next);
    whichFunc = (char *) "";
}

void ast::genCode(past node) {
    if (node == nullptr) {
//        cout<<"node transfer error"<<endl;
        return;
    }
    CodeGenerator v(node);
    node->accept(&v);
    genCode(node->left);
    genCode(node->right);
    genCode(node->next);
}

void ast::semanticCheck(past node) {
    if (node == nullptr) {
        // cout<<"node transfer error"<<endl;
        return;
    }
    TypeChecker v(node);
    node->accept(&v);
    semanticCheck(node->left);
    semanticCheck(node->right);
    semanticCheck(node->next);

}
